package gitee.derumin.lifeissohard.criteria;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import gitee.derumin.lifeissohard.lishhungersystem.LishHungerManager;
import net.minecraft.advancement.criterion.AbstractCriterion;
import net.minecraft.advancement.criterion.AbstractCriterionConditions;
import net.minecraft.predicate.NumberRange;
import net.minecraft.predicate.entity.AdvancementEntityPredicateDeserializer;
import net.minecraft.predicate.entity.AdvancementEntityPredicateSerializer;
import net.minecraft.predicate.entity.EntityPredicate;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.Identifier;
import net.minecraft.util.JsonHelper;
import org.jetbrains.annotations.Nullable;

public class NutritionEffectsCriterion extends AbstractCriterion<NutritionEffectsCriterion.Conditions> {
    static final Identifier ID = new Identifier("lifeissohard","nutrition_effect");

    public void trigger(ServerPlayerEntity player , LishHungerManager.NutritionEffects nutritionEffects){
        super.trigger(player,conditions -> conditions.matches(nutritionEffects));
    }
    @Override
    protected Conditions conditionsFromJson(JsonObject obj1, EntityPredicate.Extended playerPredicate, AdvancementEntityPredicateDeserializer predicateDeserializer) {
        JsonElement json = obj1.has("nutrition_effects")? obj1.get("nutrition_effects") : null;
        JsonObject obj2;
        if (json != null && !json.isJsonNull()){
            obj2 = JsonHelper.asObject(json,"nutrition_effects");
        }else obj2 = new JsonObject();
        return new Conditions(playerPredicate, obj2);
    }

    @Override
    public Identifier getId() {
        return ID;
    }

    public static class Conditions extends AbstractCriterionConditions{
        private final Boolean isWeak;
        private final Boolean isHungry;
        private final Boolean isStarved;
        private final Boolean isFull;
        private final Boolean isEmptyStomach;
        private final Boolean isThirsty;
        private final Boolean isWaterIntoxicated;
        private final Boolean isPoisonedByHeavyMetal;
        private final Boolean isExhausted;
        private final Boolean isDyspepsia;
        private final Boolean isLackInVA;
        private final Boolean isLackInVB;
        private final Boolean isLackInVC;
        private final Boolean isLackInIodine;
        private final Boolean isIodineExcess;
        private final Boolean isLackInStrength;
        private final Boolean isPowerful;
        private final Boolean cannotRegenerate;
        private final Boolean dieFromThirsty;
        private final Boolean dieFromWaterIntoxication;
        private final Boolean dieFromStomachRupture;
        private final Boolean dieFromGluttony;
        private final Boolean dieFromHypoglycemia;
        private final Boolean dieFromHypoglycemiaExhausted;
        private final Boolean dieFromStarve;
        private final NumberRange.FloatRange fats;
        private final NumberRange.FloatRange muscles;
        private final NumberRange.FloatRange weight;
        public Conditions(EntityPredicate.Extended entity, JsonObject obj) {
            super(ID, entity);
            this.isWeak = obj.has("is_weak")? JsonHelper.getBoolean(obj,"is_weak") : null;
            this.isHungry = obj.has("is_hungry")? JsonHelper.getBoolean(obj,"is_hungry") : null;
            this.isStarved = obj.has("is_starved")? JsonHelper.getBoolean(obj,"is_starved") : null;
            this.isFull = obj.has("is_full")? JsonHelper.getBoolean(obj,"is_full") : null;
            this.isEmptyStomach = obj.has("is_empty_stomach")? JsonHelper.getBoolean(obj,"is_empty_stomach") : null;
            this.isThirsty = obj.has("is_thirsty")? JsonHelper.getBoolean(obj,"is_thirsty") : null;
            this.isWaterIntoxicated = obj.has("is_water_intoxicated")? JsonHelper.getBoolean(obj,"is_water_intoxicated") : null;
            this.isPoisonedByHeavyMetal = obj.has("is_poisoned_by_heavy_metal")? JsonHelper.getBoolean(obj,"is_poisoned_by_heavy_metal") : null;
            this.isExhausted = obj.has("is_exhausted")? JsonHelper.getBoolean(obj,"is_exhausted") : null;
            this.isDyspepsia = obj.has("is_dyspepsia")? JsonHelper.getBoolean(obj,"is_dyspepsia") : null;
            this.isLackInVA = obj.has("is_lack_in_va")? JsonHelper.getBoolean(obj,"is_lack_in_va") : null;
            this.isLackInVB = obj.has("is_lack_in_vb")? JsonHelper.getBoolean(obj,"is_lack_in_vb") : null;
            this.isLackInVC = obj.has("is_lack_in_vc")? JsonHelper.getBoolean(obj,"is_lack_in_vc") : null;
            this.isLackInIodine = obj.has("is_lack_in_iodine")? JsonHelper.getBoolean(obj,"is_lack_in_iodine") : null;
            this.isIodineExcess = obj.has("is_iodine_excess")? JsonHelper.getBoolean(obj,"is_iodine_excess") : null;
            this.isLackInStrength = obj.has("is_lack_in_strength")? JsonHelper.getBoolean(obj,"is_lack_in_strength") : null;
            this.isPowerful = obj.has("is_powerful")? JsonHelper.getBoolean(obj,"is_powerful") : null;
            this.cannotRegenerate = obj.has("cannot_regenerate")? JsonHelper.getBoolean(obj,"cannot_regenerate") : null;
            this.dieFromThirsty = obj.has("die_from_thirsty")? JsonHelper.getBoolean(obj,"die_from_thirsty") : null;
            this.dieFromWaterIntoxication = obj.has("die_from_water_intoxication")? JsonHelper.getBoolean(obj,"die_from_water_intoxication") : null;
            this.dieFromStomachRupture = obj.has("die_from_stomach_rupture")? JsonHelper.getBoolean(obj,"die_from_stomach_rupture") : null;
            this.dieFromGluttony = obj.has("die_from_gluttony")? JsonHelper.getBoolean(obj,"die_from_gluttony") : null;
            this.dieFromHypoglycemia = obj.has("die_from_hypoglycemia")? JsonHelper.getBoolean(obj,"die_from_hypoglycemia") : null;
            this.dieFromHypoglycemiaExhausted = obj.has("die_from_hypoglycemia_exhausted")? JsonHelper.getBoolean(obj,"die_from_hypoglycemia_exhausted") : null;
            this.dieFromStarve = obj.has("die_from_starve")? JsonHelper.getBoolean(obj,"die_from_starve") : null;
            this.fats = obj.has("fats")? NumberRange.FloatRange.fromJson(obj.get("fats")) : NumberRange.FloatRange.ANY;
            this.muscles = obj.has("muscles")? NumberRange.FloatRange.fromJson(obj.get("muscles")) : NumberRange.FloatRange.ANY;
            this.weight = obj.has("weight")? NumberRange.FloatRange.fromJson(obj.get("weight")) : NumberRange.FloatRange.ANY;
        }

        protected Conditions(ConditionBuilder builder){
            super(ID, builder.entity);
            this.isWeak = builder.isWeak;
            this.isHungry = builder.isHungry;
            this.isStarved = builder.isStarved;
            this.isFull = builder.isFull;
            this.isEmptyStomach = builder.isEmptyStomach;
            this.isThirsty = builder.isThirsty;
            this.isWaterIntoxicated = builder.isWaterIntoxicated;
            this.isPoisonedByHeavyMetal = builder.isPoisonedByHeavyMetal;
            this.isExhausted = builder.isExhausted;
            this.isDyspepsia = builder.isDyspepsia;
            this.isLackInVA = builder.isLackInVA;
            this.isLackInVB = builder.isLackInVB;
            this.isLackInVC = builder.isLackInVC;
            this.isLackInIodine = builder.isLackInIodine;
            this.isIodineExcess = builder.isIodineExcess;
            this.isLackInStrength = builder.isLackInStrength;
            this.isPowerful = builder.isPowerful;
            this.cannotRegenerate = builder.cannotRegenerate;
            this.dieFromThirsty = builder.dieFromThirsty;
            this.dieFromWaterIntoxication = builder.dieFromWaterIntoxication;
            this.dieFromStomachRupture = builder.dieFromStomachRupture;
            this.dieFromGluttony = builder.dieFromGluttony;
            this.dieFromHypoglycemia = builder.dieFromHypoglycemia;
            this.dieFromHypoglycemiaExhausted = builder.dieFromHypoglycemiaExhausted;
            this.dieFromStarve = builder.dieFromStarve;
            this.fats = builder.fats;
            this.muscles = builder.muscles;
            this.weight = builder.weight;
        }


        public JsonObject toJson(AdvancementEntityPredicateSerializer predicateSerializer) {
            JsonObject obj1 = super.toJson(predicateSerializer);
            JsonObject obj2 = new JsonObject();
            if (this.isWeak != null){
                obj2.addProperty("is_weak",this.isWeak);
            }
            if (this.isHungry != null){
                obj2.addProperty("is_hungry",this.isHungry);
            }
            if (this.isStarved != null){
                obj2.addProperty("is_starved",this.isStarved);
            }
            if (this.isThirsty != null){
                obj2.addProperty("is_thirsty",this.isThirsty);
            }
            if (this.isFull != null){
                obj2.addProperty("is_full",this.isFull);
            }
            if (this.isEmptyStomach != null){
                obj2.addProperty("is_empty_stomach",this.isEmptyStomach);
            }
            if (this.isWaterIntoxicated != null){
                obj2.addProperty("is_water_intoxicated",this.isWaterIntoxicated);
            }
            if (this.isPoisonedByHeavyMetal != null){
                obj2.addProperty("is_poisoned_by_heavy_metal",this.isPoisonedByHeavyMetal);
            }
            if (this.isExhausted != null){
                obj2.addProperty("is_exhausted",this.isExhausted);
            }
            if (this.isDyspepsia != null){
                obj2.addProperty("is_dyspepsia",this.isDyspepsia);
            }
            if (this.isLackInVA != null){
                obj2.addProperty("is_lack_in_va",this.isLackInVA);
            }
            if (this.isLackInVB != null){
                obj2.addProperty("is_lack_in_vb",this.isLackInVB);
            }
            if (this.isLackInVC != null){
                obj2.addProperty("is_lack_in_vc",this.isLackInVC);
            }
            if (this.isLackInIodine != null){
                obj2.addProperty("is_lack_in_iodine",this.isLackInIodine);
            }
            if (this.isIodineExcess != null){
                obj2.addProperty("is_iodine_excess",this.isIodineExcess);
            }
            if (this.isLackInStrength != null){
                obj2.addProperty("is_lack_in_strength",this.isLackInStrength);
            }
            if (this.isPowerful != null){
                obj2.addProperty("is_powerful",this.isPowerful);
            }
            if (this.cannotRegenerate != null){
                obj2.addProperty("cannot_regenerate",this.cannotRegenerate);
            }
            if (this.dieFromThirsty != null){
                obj2.addProperty("die_from_thirsty",this.dieFromThirsty);
            }
            if (this.dieFromWaterIntoxication != null){
                obj2.addProperty("die_from_water_intoxication",this.dieFromWaterIntoxication);
            }
            if (this.dieFromStomachRupture != null){
                obj2.addProperty("die_from_stomach_rupture",this.dieFromStomachRupture);
            }
            if (this.dieFromGluttony != null){
                obj2.addProperty("die_from_gluttony",this.dieFromGluttony);
            }
            if (this.dieFromHypoglycemia != null){
                obj2.addProperty("die_from_hypoglycemia",this.dieFromHypoglycemia);
            }
            if (this.dieFromHypoglycemiaExhausted != null){
                obj2.addProperty("die_from_hypoglycemia_exhausted",this.dieFromHypoglycemiaExhausted);
            }
            if (this.dieFromStarve != null){
                obj2.addProperty("die_from_starve",this.dieFromStarve);
            }
            obj2.add("fats",this.fats.toJson());
            obj2.add("muscles",this.muscles.toJson());
            obj2.add("weight",this.weight.toJson());
            obj1.add("nutrition_effects", obj2);
            return obj1;
        }

        public boolean matches(LishHungerManager.NutritionEffects nutritionEffects){
            if (this.isWeak != null && this.isWeak != nutritionEffects.isWeak){
                return false;
            }else if (this.isHungry != null && this.isHungry != nutritionEffects.isHungry){
                return false;
            }else if (this.isStarved != null && this.isStarved!= nutritionEffects.isStarved){
                return false;
            }else if (this.isThirsty != null && this.isThirsty != nutritionEffects.isThirsty){
                return false;
            }else if (this.isFull != null && this.isFull != nutritionEffects.isFull){
                return false;
            }else if (this.isEmptyStomach != null && this.isEmptyStomach != nutritionEffects.isEmptyStomach){
                return false;
            }else if (this.isWaterIntoxicated != null && this.isWaterIntoxicated != nutritionEffects.isWaterIntoxicated){
                return false;
            }else if (this.isPoisonedByHeavyMetal != null && this.isPoisonedByHeavyMetal != nutritionEffects.isPoisonedByHeavyMetal){
                return false;
            }else if (this.isExhausted != null && this.isExhausted != nutritionEffects.isExhausted){
                return false;
            }else if (this.isDyspepsia != null && this.isDyspepsia != nutritionEffects.isDyspepsia){
                return false;
            }else if (this.isLackInVA != null && this.isLackInVA != nutritionEffects.isLackInVA){
                return false;
            }else if (this.isLackInVB != null && this.isLackInVB != nutritionEffects.isLackInVB){
                return false;
            }else if (this.isLackInVC != null && this.isLackInVC != nutritionEffects.isLackInVC){
                return false;
            }else if (this.isLackInIodine != null && this.isLackInIodine != nutritionEffects.isLackInIodine){
                return false;
            }else if (this.isIodineExcess != null && this.isIodineExcess != nutritionEffects.isIodineExcess){
                return false;
            }else if (this.isLackInStrength != null && this.isLackInStrength != nutritionEffects.isLackInStrength){
                return false;
            }else if (this.isPowerful != null && this.isPowerful != nutritionEffects.isPowerful){
                return false;
            }else if (this.cannotRegenerate != null && this.cannotRegenerate != nutritionEffects.cannotRegenerate){
                return false;
            }else if (this.dieFromThirsty != null && this.dieFromThirsty != nutritionEffects.dieFromThirsty){
                return false;
            }else if (this.dieFromWaterIntoxication != null && this.dieFromWaterIntoxication != nutritionEffects.dieFromWaterIntoxication){
                return false;
            }else if (this.dieFromStomachRupture != null && this.dieFromStomachRupture != nutritionEffects.dieFromStomachRupture){
                return false;
            }else if (this.dieFromGluttony != null && this.dieFromGluttony != nutritionEffects.dieFromGluttony){
                return false;
            }else if (this.dieFromHypoglycemia != null && this.dieFromHypoglycemia != nutritionEffects.dieFromHypoglycemia){
                return false;
            }else if (this.dieFromHypoglycemiaExhausted != null && this.dieFromHypoglycemiaExhausted != nutritionEffects.dieFromHypoglycemiaExhausted){
                return false;
            }else if (this.dieFromStarve != null && this.dieFromStarve != nutritionEffects.dieFromStarve){
                return false;
            }else if (!this.fats.test(nutritionEffects.fats)){
                return false;
            }else if (!this.muscles.test(nutritionEffects.muscles)){
                return false;
            }else return this.weight.test(nutritionEffects.weight);
        }
    }

    public static class ConditionBuilder{
        protected EntityPredicate.Extended entity = EntityPredicate.Extended.EMPTY;
        protected Boolean isWeak = null;
        protected Boolean isHungry = null;
        protected Boolean isStarved = null;
        protected Boolean isFull = null;
        protected Boolean isEmptyStomach = null;
        protected Boolean isThirsty = null;
        protected Boolean isWaterIntoxicated = null;
        protected Boolean isPoisonedByHeavyMetal = null;
        protected Boolean isExhausted = null;
        protected Boolean isDyspepsia = null;
        protected Boolean isLackInVA = null;
        protected Boolean isLackInVB = null;
        protected Boolean isLackInVC = null;
        protected Boolean isLackInIodine = null;
        protected Boolean isIodineExcess = null;
        protected Boolean isLackInStrength = null;
        protected Boolean isPowerful = null;
        protected Boolean cannotRegenerate = null;
        protected Boolean dieFromThirsty = null;
        protected Boolean dieFromWaterIntoxication = null;
        protected Boolean dieFromStomachRupture = null;
        protected Boolean dieFromGluttony = null;
        protected Boolean dieFromHypoglycemia = null;
        protected Boolean dieFromHypoglycemiaExhausted = null;
        protected Boolean dieFromStarve = null;
        protected NumberRange.FloatRange fats = NumberRange.FloatRange.ANY;
        protected NumberRange.FloatRange muscles = NumberRange.FloatRange.ANY;
        protected NumberRange.FloatRange weight = NumberRange.FloatRange.ANY;

        public Conditions build(){
            return new Conditions(this);
        }

        public ConditionBuilder addPlayer(EntityPredicate.Extended playerEntity){
            this.entity = playerEntity;
            return this;
        }

        public ConditionBuilder isWeak(boolean bl){
            this.isWeak = bl;
            return this;
        }

        public ConditionBuilder isHungry(boolean bl){
            this.isHungry = bl;
            return this;
        }

        public ConditionBuilder isStarved(boolean bl){
            this.isStarved = bl;
            return this;
        }

        public ConditionBuilder isFull(boolean bl){
            this.isFull = bl;
            return this;
        }

        public ConditionBuilder isEmptyStomach(boolean bl){
            this.isEmptyStomach = bl;
            return this;
        }

        public ConditionBuilder isThirsty(boolean bl){
            this.isThirsty = bl;
            return this;
        }

        public ConditionBuilder isWaterIntoxicated(boolean bl){
            this.isWaterIntoxicated = bl;
            return this;
        }

        public ConditionBuilder isPoisonedByHeavyMetal(boolean bl){
            this.isPoisonedByHeavyMetal = bl;
            return this;
        }

        public ConditionBuilder isExhausted(boolean bl){
            this.isExhausted = bl;
            return this;
        }

        public ConditionBuilder isDyspepsia(boolean bl){
            this.isDyspepsia = bl;
            return this;
        }

        public ConditionBuilder isLackInVA(boolean bl){
            this.isLackInVA = bl;
            return this;
        }

        public ConditionBuilder isLackInVB(boolean bl){
            this.isLackInVB = bl;
            return this;
        }

        public ConditionBuilder isLackInVC(boolean bl){
            this.isLackInVC = bl;
            return this;
        }

        public ConditionBuilder isLackInIodine(boolean bl){
            this.isLackInIodine = bl;
            return this;
        }

        public ConditionBuilder isIodineExcess(boolean bl){
            this.isIodineExcess = bl;
            return this;
        }

        public ConditionBuilder isLackInStrength(boolean bl){
            this.isLackInStrength = bl;
            return this;
        }

        public ConditionBuilder isPowerful(boolean bl){
            this.isPowerful = bl;
            return this;
        }

        public ConditionBuilder cannotRegenerate(boolean bl){
            this.cannotRegenerate = bl;
            return this;
        }

        public ConditionBuilder dieFromThirsty(boolean bl){
            this.dieFromThirsty = bl;
            return this;
        }

        public ConditionBuilder dieFromWaterIntoxication(boolean bl){
            this.dieFromWaterIntoxication = bl;
            return this;
        }

        public ConditionBuilder dieFromStomachRupture(boolean bl){
            this.dieFromStomachRupture = bl;
            return this;
        }

        public ConditionBuilder dieFromGluttony(boolean bl){
            this.dieFromGluttony = bl;
            return this;
        }


        public ConditionBuilder dieFromHypoglycemia(boolean bl){
            this.dieFromHypoglycemia = bl;
            return this;
        }

        public ConditionBuilder dieFromHypoglycemiaExhausted(boolean bl){
            this.dieFromHypoglycemiaExhausted = bl;
            return this;
        }

        public ConditionBuilder dieFromStarve(boolean bl){
            this.dieFromStarve = bl;
            return this;
        }

        public ConditionBuilder fats(@Nullable Double max,@Nullable Double min){
            if (max != null && min != null){
                this.fats = NumberRange.FloatRange.between(min,max);
            } else if (max != null) {
                this.fats = NumberRange.FloatRange.atMost(max);
            } else if (min != null) {
                this.fats = NumberRange.FloatRange.atLeast(min);
            }
            return this;
        }

        public ConditionBuilder muscles(@Nullable Double max,@Nullable Double min){
            if (max != null && min != null){
                this.muscles = NumberRange.FloatRange.between(min,max);
            } else if (max != null) {
                this.muscles = NumberRange.FloatRange.atMost(max);
            } else if (min != null) {
                this.muscles = NumberRange.FloatRange.atLeast(min);
            }
            return this;
        }

        public ConditionBuilder weight(@Nullable Double max,@Nullable Double min){
            if (max != null && min != null){
                this.weight = NumberRange.FloatRange.between(min,max);
            } else if (max != null) {
                this.weight = NumberRange.FloatRange.atMost(max);
            } else if (min != null) {
                this.weight = NumberRange.FloatRange.atLeast(min);
            }
            return this;
        }
    }
}
